//
// Created by tcj on 2022/7/16.
//

#include "HTTPconnection.h"

namespace tcj{
    const char* HTTPconnection::srcDir;
    std::atomic<int> HTTPconnection::userCount;
    bool HTTPconnection::isET;

    HTTPconnection::HTTPconnection() {
        fd_ =-1;
        addr_ = {0};
        isCLose_ = true;
    }

    HTTPconnection::~HTTPconnection() {
        closeHttpConn();
    }

    void HTTPconnection::closeHttpConn() {
        response_.unmapFile();
        if (isCLose_ == false){
            isCLose_ = true;
            userCount --;
            close(fd_);
        }
    }

    void HTTPconnection::initHttpConn(int socketFd, const sockaddr_in &addr) {
        assert(socketFd>0);
        userCount++;
        addr_ = addr;
        fd_ = socketFd;
        writeBuffer_.initPtr();
        readBuffer_.initPtr();
        isCLose_ = false;
    }

    int HTTPconnection::getFd() const {
        return fd_;
    }

    sockaddr_in HTTPconnection::getAddr() const {
        return addr_;
    }

    int HTTPconnection::getPort() const {
        return addr_.sin_port;
    }

    const char *HTTPconnection::getIP() const {
        return inet_ntoa(addr_.sin_addr);
    }

    size_t HTTPconnection::readBuffer(int *saveErrno) {
        ssize_t len =-1;
        do{
            len = readBuffer_.ReadFd(fd_,saveErrno);
            if (len<=0) break;
        } while (isET);
        return len;
    }

    size_t HTTPconnection::writeBuffer(int *saveErrno) {
        ssize_t len=-1;
        do {
            len = writev(fd_,iov_,iovCnt_);
            if (len<=0){
                *saveErrno = errno;
                break;
            }
            if (iov_[0].iov_len + iov_[1].iov_len == 0){
                break;
            }else if(static_cast<size_t>(len) > iov_[0].iov_len){
                iov_[1].iov_base = (uint8_t*)iov_[1].iov_base+(len - iov_[0].iov_len);
                iov_[1].iov_len -= (len - iov_[0].iov_len);
                if (iov_[0].iov_len){
                    writeBuffer_.initPtr();
                    iov_[0].iov_len =0;
                }
            } else{
                iov_[0].iov_base = (uint8_t*)iov_[0].iov_base +len;
                iov_[0].iov_len = len;
                writeBuffer_.updateReadPtr(len);
            }

        } while (isET || writeBytes() > 10240);
        return len;
    }


    bool HTTPconnection::handleHttpConn() {
        request_.init();
        if (readBuffer_.readableBytes() <=0){
            return false;
        }else if(request_.parse(readBuffer_)){
            response_.init(srcDir,request_.path(),request_.isKeepAlive(),200);
        }else{
            response_.init(srcDir,request_.path(), false,400);
        }

        response_.makeResponse(writeBuffer_);
        iov_[0].iov_base =  const_cast<char*>(writeBuffer_.curReadPtr());
        iov_[0].iov_len = writeBuffer_.readableBytes();
        iovCnt_ = 1;

        if (response_.fileLen()>0 && response_.file()){
            iov_[1].iov_base = response_.file();
            iov_[1].iov_len = response_.fileLen();
            iovCnt_ = 2;
        }
        return true;

    }


}